package model;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import model.AI.MapInfo;

/**
 * This Class is a type of Arena Action that is sent to the game server and
 * specifies that combat is to occur. That's about it.
 * 
 * @author David's David Shefchik, Xiaotian Chang
 * 
 * 
 * 
 */
@SuppressWarnings("serial")
public class Combat extends ArmyAction {

	private ArrayList<Integer> attackerDice;
	private ArrayList<Integer> defenderDice;

	private int attackerDiceOption;
	private int defenderDiceOption;
	private boolean conquered;

	/**
	 * The constructor for combat takes in an attacking territory and a
	 * defending territory. It calls the constructor of its army actions
	 * superclass, then sets conquered to false. It accesses the owners' dice
	 * options and sets them. Then checks to see if the comabt is valid. If it
	 * is, it carries out the combat.
	 * 
	 * @param attacker
	 *            The attacking territory
	 * @param defender
	 *            The defending territory
	 */
	public Combat(Territory attacker, Territory defender) {
		super(attacker, defender);
		conquered = false;
		attackerDiceOption = attacker.getRuler().getDiceAttack();
		defenderDiceOption = defender.getRuler().getDiceDefend();
		if (this.getTargetTerritory().getTroopNumber() != 0
				&& originTerritory.getTroopNumber() > 1
				&& !originTerritory.getRuler().equals(
						targetTerritory.getRuler())) {
			combat();

		}

	}

	/**
	 * Returns an integer representing the number of troops in the attacking
	 * territory
	 * 
	 * @return the number of troops from attack territory.
	 */
	public int attackerTroop() {
		return originTerritory.getTroopNumber();
	}

	/**
	 * Returns an integer representing the number of troops in the defending
	 * territory
	 * 
	 * @return the number of troops from defender troop.
	 */
	public int defenderTroop() {
		return targetTerritory.getTroopNumber();
	}

	/**
	 * Says whether the target territory was conquered after a new combat action
	 * was called
	 * 
	 * @return Yes if it was conquered. No if it was not
	 */
	public boolean wasConquered() {
		return conquered;
	}

	/**
	 * Returns a sorted ArrayList (ascending order) of integers, representing
	 * the dice the attacker rolled during combat
	 * 
	 * @return An ArrayList of integers sorted in ascending order, represents
	 *         the dice the attacker rolled
	 */
	public List<Integer> getAttackerDice() {
		return attackerDice;
	}

	/**
	 * Returns a sorted ArrayList (ascending order) of integers, representing
	 * the dice the defender rolled during combat
	 * 
	 * @return An ArrayList of integers sorted in ascending order, represents
	 *         the dice the defender rolled
	 */
	public List<Integer> getDefenderDice() {
		return defenderDice;
	}

	private void combat() {

		System.out.println(originTerritory.getTerritoryName() + " attacking "
				+ targetTerritory.getTerritoryName());
		int attackTroop = attackerTroop() - 1;
		int defenderTroop = defenderTroop();
		ArrayList<Integer> attacks = new ArrayList<Integer>();
		ArrayList<Integer> defends = new ArrayList<Integer>();

		if (attackTroop < attackerDiceOption)
			for (int i = 0; i < attackTroop; i++) {
				attacks.add((int) (Math.random() * 6 + 1));
			}
		else {
			for (int i = 0; i < attackerDiceOption; i++) {
				attacks.add((int) (Math.random() * 6 + 1));
			}
		}

		if (defenderTroop < defenderDiceOption)
			for (int i = 0; i < defenderTroop; i++) {
				defends.add((int) (Math.random() * 6 + 1));
			}
		else
			for (int i = 0; i < defenderDiceOption; i++) {
				defends.add((int) (Math.random() * 6 + 1));
			}

		Collections.sort(attacks);
		Collections.sort(defends);
		attackerDice = attacks;
		defenderDice = defends;

		System.out.print("\nAttacker: ");
		for (int j = attacks.size() - 1; j >= 0; j--) {
			System.out.print(attacks.get(j) + " ");
		}
		System.out.print("\nDefender: ");
		for (int j = defends.size() - 1; j >= 0; j--) {
			System.out.print(defends.get(j) + " ");
		}

		for (int i = 0; i < 2; i++) {
			if (attacks.size() > 0 && defends.size() > 0) {

				int attackMax = attacks.get(attacks.size() - 1);
				attacks.remove((Object) attackMax);

				int defendMax = defends.get(defends.size() - 1);
				defends.remove((Object) defendMax);

				if (attackMax > defendMax) {
					targetTerritory.removeTroop(1);
				} else {
					originTerritory.removeTroop(1);
				}

			}
		}

		System.out.println("\nAttacker troops: "
				+ originTerritory.getTroopNumber());
		System.out.println("\nDefender troops: "
				+ targetTerritory.getTroopNumber());
		if (targetTerritory.getTroopNumber() == 0) {// The territory was
			// conquered
			conquered = true;
			originTerritory.getRuler().setCardEligible(true);
			targetTerritory.setRuler(originTerritory.getRuler());
			if (originTerritory.getRuler() instanceof model.AI.SimpleCyborg) {
				System.out.println(" simpleAI conquered and moving");
				new model.Movement(originTerritory, targetTerritory,
						originTerritory.getTroopNumber() - 1);
			} else if (originTerritory.getRuler() instanceof model.AI.ExpertCyborg) {
				System.out.println(" expertAI conquered and moving");
				if (!MapInfo.hasBorderingEnemyTerritories(originTerritory
						.getRuler(), originTerritory)) {
					new model.Movement(originTerritory, targetTerritory,
							originTerritory.getTroopNumber() - 1);
				} else
					new model.Movement(originTerritory, targetTerritory, Math
							.min(originTerritory.getTroopNumber() - 1, 3));
			}

		}
	}
}
